{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "061374ac",
   "metadata": {},
   "source": [
    "### AlexNet代码实现"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "a4d62b41",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入必要的库，torchinfo用于查看模型结构\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "from torchinfo import summary"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "52eff219",
   "metadata": {},
   "source": [
    "### 结构定义"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "057ce823",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义AlexNet的网络结构\n",
    "class AlexNet(nn.Module):\n",
    "    def __init__(self, num_classes=1000, dropout=0.5):\n",
    "        super().__init__()\n",
    "        # 定义卷积层\n",
    "        self.features = nn.Sequential(\n",
    "            # 卷积+ReLU+最大池化\n",
    "            nn.Conv2d(3, 64, kernel_size=11, stride=4, padding=2),\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.MaxPool2d(kernel_size=3, stride=2),\n",
    "            # 卷积+ReLU+最大池化\n",
    "            nn.Conv2d(64, 192, kernel_size=5, padding=2),\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.MaxPool2d(kernel_size=3, stride=2),\n",
    "            # 卷积+ReLU\n",
    "            nn.Conv2d(192, 384, kernel_size=3, padding=1),\n",
    "            nn.ReLU(inplace=True),\n",
    "            # 卷积+ReLU\n",
    "            nn.Conv2d(384, 256, kernel_size=3, padding=1),\n",
    "            nn.ReLU(inplace=True),\n",
    "            # 卷积+ReLU\n",
    "            nn.Conv2d(256, 256, kernel_size=3, padding=1),\n",
    "            nn.ReLU(inplace=True),\n",
    "            # 最大池化\n",
    "            nn.MaxPool2d(kernel_size=3, stride=2),\n",
    "        )\n",
    "        # 定义全连接层\n",
    "        self.classifier = nn.Sequential(\n",
    "            # Dropout+全连接层+ReLU\n",
    "            nn.Dropout(p=dropout),\n",
    "            nn.Linear(256 * 6 * 6, 4096),\n",
    "            nn.ReLU(inplace=True),\n",
    "            # Dropout+全连接层+ReLU\n",
    "            nn.Dropout(p=dropout),\n",
    "            nn.Linear(4096, 4096),\n",
    "            nn.ReLU(inplace=True),\n",
    "            # 全连接层\n",
    "            nn.Linear(4096, num_classes),\n",
    "        )\n",
    "\n",
    "    # 定义前向传播函数\n",
    "    def forward(self, x):\n",
    "        # 先经过feature提取特征，flatten后送入全连接层\n",
    "        x = self.features(x)\n",
    "        x = torch.flatten(x, 1)\n",
    "        x = self.classifier(x)\n",
    "        return x"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "496298fd",
   "metadata": {},
   "source": [
    "### 网络结构"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "3ebca16f",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "==========================================================================================\n",
       "Layer (type:depth-idx)                   Output Shape              Param #\n",
       "==========================================================================================\n",
       "AlexNet                                  [1, 1000]                 --\n",
       "├─Sequential: 1-1                        [1, 256, 6, 6]            --\n",
       "│    └─Conv2d: 2-1                       [1, 64, 55, 55]           23,296\n",
       "│    └─ReLU: 2-2                         [1, 64, 55, 55]           --\n",
       "│    └─MaxPool2d: 2-3                    [1, 64, 27, 27]           --\n",
       "│    └─Conv2d: 2-4                       [1, 192, 27, 27]          307,392\n",
       "│    └─ReLU: 2-5                         [1, 192, 27, 27]          --\n",
       "│    └─MaxPool2d: 2-6                    [1, 192, 13, 13]          --\n",
       "│    └─Conv2d: 2-7                       [1, 384, 13, 13]          663,936\n",
       "│    └─ReLU: 2-8                         [1, 384, 13, 13]          --\n",
       "│    └─Conv2d: 2-9                       [1, 256, 13, 13]          884,992\n",
       "│    └─ReLU: 2-10                        [1, 256, 13, 13]          --\n",
       "│    └─Conv2d: 2-11                      [1, 256, 13, 13]          590,080\n",
       "│    └─ReLU: 2-12                        [1, 256, 13, 13]          --\n",
       "│    └─MaxPool2d: 2-13                   [1, 256, 6, 6]            --\n",
       "├─Sequential: 1-2                        [1, 1000]                 --\n",
       "│    └─Dropout: 2-14                     [1, 9216]                 --\n",
       "│    └─Linear: 2-15                      [1, 4096]                 37,752,832\n",
       "│    └─ReLU: 2-16                        [1, 4096]                 --\n",
       "│    └─Dropout: 2-17                     [1, 4096]                 --\n",
       "│    └─Linear: 2-18                      [1, 4096]                 16,781,312\n",
       "│    └─ReLU: 2-19                        [1, 4096]                 --\n",
       "│    └─Linear: 2-20                      [1, 1000]                 4,097,000\n",
       "==========================================================================================\n",
       "Total params: 61,100,840\n",
       "Trainable params: 61,100,840\n",
       "Non-trainable params: 0\n",
       "Total mult-adds (M): 714.68\n",
       "==========================================================================================\n",
       "Input size (MB): 0.60\n",
       "Forward/backward pass size (MB): 3.95\n",
       "Params size (MB): 244.40\n",
       "Estimated Total Size (MB): 248.96\n",
       "=========================================================================================="
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 查看模型结构及参数量，input_size表示示例输入数据的维度信息\n",
    "summary(AlexNet(), input_size=(1, 3, 224, 224))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4b837b9c",
   "metadata": {},
   "source": [
    "### torchvision"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "66df0e0e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "==========================================================================================\n",
       "Layer (type:depth-idx)                   Output Shape              Param #\n",
       "==========================================================================================\n",
       "AlexNet                                  [1, 1000]                 --\n",
       "├─Sequential: 1-1                        [1, 256, 6, 6]            --\n",
       "│    └─Conv2d: 2-1                       [1, 64, 55, 55]           23,296\n",
       "│    └─ReLU: 2-2                         [1, 64, 55, 55]           --\n",
       "│    └─MaxPool2d: 2-3                    [1, 64, 27, 27]           --\n",
       "│    └─Conv2d: 2-4                       [1, 192, 27, 27]          307,392\n",
       "│    └─ReLU: 2-5                         [1, 192, 27, 27]          --\n",
       "│    └─MaxPool2d: 2-6                    [1, 192, 13, 13]          --\n",
       "│    └─Conv2d: 2-7                       [1, 384, 13, 13]          663,936\n",
       "│    └─ReLU: 2-8                         [1, 384, 13, 13]          --\n",
       "│    └─Conv2d: 2-9                       [1, 256, 13, 13]          884,992\n",
       "│    └─ReLU: 2-10                        [1, 256, 13, 13]          --\n",
       "│    └─Conv2d: 2-11                      [1, 256, 13, 13]          590,080\n",
       "│    └─ReLU: 2-12                        [1, 256, 13, 13]          --\n",
       "│    └─MaxPool2d: 2-13                   [1, 256, 6, 6]            --\n",
       "├─AdaptiveAvgPool2d: 1-2                 [1, 256, 6, 6]            --\n",
       "├─Sequential: 1-3                        [1, 1000]                 --\n",
       "│    └─Dropout: 2-14                     [1, 9216]                 --\n",
       "│    └─Linear: 2-15                      [1, 4096]                 37,752,832\n",
       "│    └─ReLU: 2-16                        [1, 4096]                 --\n",
       "│    └─Dropout: 2-17                     [1, 4096]                 --\n",
       "│    └─Linear: 2-18                      [1, 4096]                 16,781,312\n",
       "│    └─ReLU: 2-19                        [1, 4096]                 --\n",
       "│    └─Linear: 2-20                      [1, 1000]                 4,097,000\n",
       "==========================================================================================\n",
       "Total params: 61,100,840\n",
       "Trainable params: 61,100,840\n",
       "Non-trainable params: 0\n",
       "Total mult-adds (M): 714.68\n",
       "==========================================================================================\n",
       "Input size (MB): 0.60\n",
       "Forward/backward pass size (MB): 3.95\n",
       "Params size (MB): 244.40\n",
       "Estimated Total Size (MB): 248.96\n",
       "=========================================================================================="
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 查看torchvision自带的模型结构及参数量\n",
    "from torchvision import models\n",
    "summary(models.alexnet(), input_size=(1, 3, 224, 224))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b09a91d",
   "metadata": {},
   "source": [
    "### 模型训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "a52ec145",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 0 Loss: 2.056710654079528 Acc: 0.00980392156862745\n",
      "Epoch: 50 Loss: 1.81992189286025 Acc: 0.2568627450980392\n",
      "Epoch: 100 Loss: 1.7028522357427933 Acc: 0.40588235294117647\n",
      "Epoch: 150 Loss: 1.655522045895868 Acc: 0.3480392156862745\n",
      "Epoch: 200 Loss: 1.4933272565532425 Acc: 0.5362745098039216\n",
      "Epoch: 250 Loss: 1.4933084530330363 Acc: 0.592156862745098\n",
      "Epoch: 300 Loss: 1.3643970408766197 Acc: 0.6303921568627451\n",
      "Epoch: 350 Loss: 1.349363543060287 Acc: 0.6107843137254902\n",
      "Epoch: 400 Loss: 1.3387303540492963 Acc: 0.6411764705882353\n",
      "Epoch: 450 Loss: 1.2464284899548854 Acc: 0.6696078431372549\n",
      "100%|██████████| 500/500 [2:41:21<00:00, 19.36s/it]\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy: 0.657843137254902\n"
     ]
    }
   ],
   "source": [
    "# 导入必要的库\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "from torch.utils.data import DataLoader\n",
    "from torchvision import datasets, transforms, models\n",
    "from tqdm import *\n",
    "import numpy as np\n",
    "import sys\n",
    "\n",
    "# 设备检测，若未检测到cuda设备则在CPU上运行\n",
    "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
    "\n",
    "# 设置随机种子\n",
    "torch.manual_seed(0)\n",
    "\n",
    "# 定义模型、优化器、损失函数\n",
    "model = AlexNet(num_classes=102).to(device)\n",
    "optimizer = optim.SGD(model.parameters(), lr=0.002, momentum=0.9)\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "\n",
    "# 设置训练集的数据变换，进行数据增强\n",
    "trainform_train = transforms.Compose([\n",
    "    transforms.RandomRotation(30), # 随机旋转 -30度到30度之间\n",
    "    transforms.RandomResizedCrop((224, 224)), # 随机比例裁剪并进行resize\n",
    "    transforms.RandomHorizontalFlip(p = 0.5), # 随机水平翻转\n",
    "    transforms.RandomVerticalFlip(p = 0.5), # 随机垂直翻转\n",
    "    transforms.ToTensor(),  # 将数据转换为张量\n",
    "    # 对三通道数据进行归一化(均值，标准差)，数值是从ImageNet数据集上的百万张图片中随机抽样计算得到\n",
    "    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n",
    "])\n",
    "\n",
    "# 设置测试集的数据变换，不进行数据增强，仅使用resize和归一化\n",
    "transform_test = transforms.Compose([\n",
    "    transforms.Resize((224, 224)),  # resize\n",
    "    transforms.ToTensor(),  # 将数据转换为张量\n",
    "    # 对三通道数据进行归一化(均值，标准差)，数值是从ImageNet数据集上的百万张图片中随机抽样计算得到\n",
    "    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n",
    "])\n",
    "\n",
    "# 加载训练数据，需要特别注意的是Flowers102数据集，test簇的数据量较多些，所以这里使用\"test\"作为训练集\n",
    "train_dataset = datasets.Flowers102(root='../data/flowers102', split=\"test\", \n",
    "                                    download=True, transform=trainform_train)\n",
    "# 实例化训练数据加载器\n",
    "train_loader = DataLoader(train_dataset, batch_size=256, shuffle=True, num_workers=6)\n",
    "# 加载测试数据，使用\"train\"作为测试集\n",
    "test_dataset = datasets.Flowers102(root='../data/flowers102', split=\"train\", \n",
    "                                   download=True, transform=transform_test)\n",
    "# 实例化测试数据加载器\n",
    "test_loader = DataLoader(test_dataset, batch_size=256, shuffle=False, num_workers=6)\n",
    "\n",
    "# 设置epoch数并开始训练\n",
    "num_epochs = 500  # 设置epoch数\n",
    "loss_history = []  # 创建损失历史记录列表\n",
    "acc_history = []   # 创建准确率历史记录列表\n",
    "\n",
    "# tqdm用于显示进度条并评估任务时间开销\n",
    "for epoch in tqdm(range(num_epochs), file=sys.stdout):\n",
    "    # 记录损失和预测正确数\n",
    "    total_loss = 0\n",
    "    total_correct = 0\n",
    "    \n",
    "    # 批量训练\n",
    "    model.train()\n",
    "    for inputs, labels in train_loader:\n",
    "        # 将数据转移到指定计算资源设备上\n",
    "        inputs = inputs.to(device)\n",
    "        labels = labels.to(device)\n",
    "        \n",
    "        # 预测、损失函数、反向传播\n",
    "        optimizer.zero_grad()\n",
    "        outputs = model(inputs)\n",
    "        loss = criterion(outputs, labels)\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        \n",
    "        # 记录训练集loss\n",
    "        total_loss += loss.item()\n",
    "    \n",
    "    # 测试模型，不计算梯度\n",
    "    model.eval()\n",
    "    with torch.no_grad():\n",
    "        for inputs, labels in test_loader:\n",
    "            # 将数据转移到指定计算资源设备上\n",
    "            inputs = inputs.to(device)\n",
    "            labels = labels.to(device)\n",
    "            \n",
    "            # 预测\n",
    "            outputs = model(inputs)\n",
    "            # 记录测试集预测正确数\n",
    "            total_correct += (outputs.argmax(1) == labels).sum().item()\n",
    "        \n",
    "    # 记录训练集损失和测试集准确率\n",
    "    loss_history.append(np.log10(total_loss))  # 将损失加入损失历史记录列表，由于数值有时较大，这里取对数\n",
    "    acc_history.append(total_correct / len(test_dataset))# 将准确率加入准确率历史记录列表\n",
    "    \n",
    "    # 打印中间值\n",
    "    if epoch % 50 == 0:\n",
    "        tqdm.write(\"Epoch: {0} Loss: {1} Acc: {2}\".format(epoch, loss_history[-1], acc_history[-1]))\n",
    "\n",
    "# 使用Matplotlib绘制损失和准确率的曲线图\n",
    "import matplotlib.pyplot as plt\n",
    "plt.plot(loss_history, label='loss')\n",
    "plt.plot(acc_history, label='accuracy')\n",
    "plt.legend()\n",
    "plt.show()\n",
    "\n",
    "# 输出准确率\n",
    "print(\"Accuracy:\", acc_history[-1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6163c6f4",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
